package com.example.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringReader;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

import android.app.ActivityManagerNative;
import android.app.ActivityThread;
import android.app.AndroidAppHelper;
import android.app.Application;
import android.content.Context;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageInstallObserver;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.support.v4.os.ESQLiteOpenHelper;
import android.support.v4.os.ESettings;
import android.util.Log;

import com.example.utils.Logger;
import com.example.utils.Shell;

/**
 * 系统服务（修改此类需要重启）
 */
public final class SystemServiceImpl extends ISystemService.Stub implements Callback,
		SystemServiceMsgCode {
	private static final String TAG = "SystemServiceImpl";
	private static final String SERVICE_NAME = "System.Service";
	private static final Logger log = Logger.create(TAG);

	// dumpsys System.Service

	/**
	 * 注册系统服务，只能由Xposed调用
	 */
	public static void register() throws Exception {
		SystemServiceImpl service = new SystemServiceImpl();

		Class<?> cServiceManager = Class.forName("android.os.ServiceManager");
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
			Method mAddService = cServiceManager.getDeclaredMethod(
					"addService", String.class, IBinder.class, boolean.class);
			mAddService.invoke(null, SERVICE_NAME, service, true);
		} else {
			Method mAddService = cServiceManager.getDeclaredMethod(
					"addService", String.class, IBinder.class);
			mAddService.invoke(null, SERVICE_NAME, service);
		}
		Log.e(TAG, SERVICE_NAME + "service registed ");
	}

	// /////////////////////////////////////////////////////////////////////////
	private Set<String> watchSet = new HashSet<String>();
	private Handler mHandler;
	private Messenger mMessenger;

	private SystemServiceImpl() {
	}

	@Override
	public IBinder getMessengerBinder() {
		if (mMessenger == null) {
			synchronized (this) {
				if (mMessenger == null) {
					if (Looper.getMainLooper() == null)
						Looper.prepare();

					mHandler = new Handler(
							Looper.getMainLooper() == null ? Looper.myLooper()
									: Looper.getMainLooper(), this);
					mMessenger = new Messenger(mHandler);

					if (Looper.getMainLooper() == null)
						Looper.loop();
				}
			}
		}

		return mMessenger.getBinder();
	}

	@Override
	protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
		fout.println(SERVICE_NAME + " is running (version 2015/06/05)");
		if (watchSet.size() == 0) {
			fout.println("Empty watchSet!");
		} else {
			fout.println("watchSet:");
			for (String pkg : watchSet) {
				fout.print("\t");
				fout.println(pkg);
			}
		}
		fout.println("args:");
		for(String t : args){
			fout.print("\t");
			fout.println(t);
		}
	}

	@Override
	public void watch(String packageName) throws RemoteException {
		watchSet.add(packageName);
	}

	@Override
	public void unWatch(String packageName) throws RemoteException {
		watchSet.remove(packageName);
	}

	@Override
	public void unWatchAll() throws RemoteException {
		watchSet.clear();
	}

	@Override
	public boolean isWatched(String packageName) throws RemoteException {
		return watchSet.contains(packageName);
	}
	private Bundle bundle = new Bundle();
	@Override
	public String getString(String key, String defaultValue){
		return bundle.getString(key, defaultValue);
	}
	@Override
	public void putString(String key, String value){
		bundle.putString(key, value);
	}
	@Override
	public Bundle getBundle() throws RemoteException {
		return bundle;
	};
	// /////////////////系统级调用/////////////////////////////////////////////////////
	@Override
	public boolean handleMessage(Message msg) {
		switch (msg.what) {
		case REBOOT:
			reboot();
			break;
		case FORCE_STOP_PACKAGE:
			forceStopPackage(msg.getData().getString("p"));
			break;
		case UNINSTALL:
			uninstall(msg.getData().getString("p"));
			break;
		case INSTALL:
			install(msg.getData().getString("p"));
			break;
		case CLEAR_DATA:
			clearData(msg.getData().getString("p"));
			break;
		case CLEAR_CACHE:
			clearCache(msg.getData().getString("p"));
			break;
		case DEVICE_WAKEUP:
			deviceWakeUp(msg.getData().getLong("p"));
			break;
		case DEVICE_SLEEP:
			deviceSleep(msg.getData().getLong("p"));
			break;
		case KILLPROCESS:
			android.os.Process.killProcess(msg.arg1);
			break;
		case DELETE_SYSTEM_DB:
			if(ESQLiteOpenHelper.settings_db!=null){
				String key = msg.getData().getString("p");
				if(key!=null){
					int i = ESQLiteOpenHelper.settings_db.delete("system", "name=?", new String[]{key});
					if(i!=0){
						log.w("删除系统设置键:"+key+"=成功ret:"+i);
					}else{
						log.e("删除系统设置键失败:"+key);
					}
				}
			}else{
				log.e("未获得系统设置数据库");
			}
			break;
		default:
			return false;
		}
		return true;
	}

	/**
	 * 屏幕灭
	 */
	private void deviceSleep(long time){
		try {
			PowerManager pm = (PowerManager) AndroidAppHelper
					.currentApplication().getSystemService(Context.POWER_SERVICE);
			pm.goToSleep(time);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 屏幕亮
	 */
	private void deviceWakeUp(long time){
		try {
			PowerManager pm = (PowerManager) AndroidAppHelper
					.currentApplication().getSystemService(Context.POWER_SERVICE);
			pm.wakeUp(time);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 重启
	 */
	private void reboot() {
		Application application = AndroidAppHelper.currentApplication();
		Log.e(TAG, "application.getPackageCodePath()=" + application.getPackageCodePath());
		Log.e(TAG, "application.getPackageName()=" + application.getPackageName());
		Log.e(TAG, "Thread.currentThread().getName()=" + Thread.currentThread().getName());
		Log.e(TAG, "Process.myPid()" + Process.myPid());

		PowerManager pm = (PowerManager) application
				.getSystemService(Context.POWER_SERVICE);
		pm.reboot(null);
	}
	
	/**
	 * 强制停止
	 */
	private void forceStopPackage(String packageName) {
		Log.e(TAG, "Foce Stop: " + packageName);
		try {
			ActivityManagerNative.getDefault().forceStopPackage(
					packageName, UserHandle.myUserId());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private static final IPackageDataObserver PACKAGE_DATA_OBSERVER = new IPackageDataObserver.Stub() {
		@Override
		public void onRemoveCompleted(String packageName, boolean succeeded) {
			log.e("clear data: " + packageName + " succeeded=" + succeeded);
		}
	};

	private static final IPackageDeleteObserver PACKAGE_DELETE_OBSERVER = new IPackageDeleteObserver.Stub() {
		@Override
		public void packageDeleted(String packageName, int returnCode)
				throws RemoteException {
			log.e("delete pkg: " + packageName + " returnCode=" + returnCode);
		}
	};

	private static final IPackageInstallObserver PACKAGE_INSTALL_OBSERVER = new IPackageInstallObserver.Stub() {

		@Override
		public void packageInstalled(String packageName, int returnCode)
				throws RemoteException {
			log.e("install pkg: " + packageName + " returnCode=" + returnCode);
		}
	};

	/*
	 * 卸载软件
	 */
	private void uninstall(String packageName) {
		log.e("uninstall: " + packageName);
		try {
			AndroidAppHelper.currentApplication()
					.getPackageManager()
					.deletePackage(packageName, PACKAGE_DELETE_OBSERVER, PackageManager.DELETE_ALL_USERS);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * 安装软件
	 */
	private void install(String path) {
		log.e("install: " + path);
		try {
			AndroidAppHelper.currentApplication()
					.getPackageManager().installPackage(
							Uri.fromFile(new File(path)),
							PACKAGE_INSTALL_OBSERVER,
							PackageManager.INSTALL_REPLACE_EXISTING,
							"com.qihoo.appstore");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 清除数据
	 */
	private void clearData(String packageName) {
		log.e("Clear app data: " + packageName);
		try {
			ActivityThread.getPackageManager().clearApplicationUserData(
					packageName, PACKAGE_DATA_OBSERVER,
					UserHandle.myUserId());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 清除缓存
	 */
	private void clearCache(String packageName) {
		log.e("Clear app cache: " + packageName);
		try {
			ActivityThread.getPackageManager().deleteApplicationCacheFiles(
					packageName, PACKAGE_DATA_OBSERVER);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
